package com.jinglin.aspect;

import com.jinglin.annotation.RecordUserMessage;
import com.jinglin.component.RedisComponent;
import com.jinglin.entity.constants.Constants;
import com.jinglin.entity.dto.TokenUserInfoDto;
import com.jinglin.entity.enums.MessageTypeEnum;
import com.jinglin.entity.enums.UserActionTypeEnum;
import com.jinglin.entity.po.VideoComment;
import com.jinglin.entity.vo.ResponseVO;
import com.jinglin.service.UserMessageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.coyote.Response;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Component
@Aspect
@Slf4j
public class UserMessageOperationAspect {
    @Autowired
    private RedisComponent redisComponent;
    @Autowired
    private UserMessageService userMessageService;
    //通过around，我们可以对方法的返回值，进行二次修改。进行修饰
    @Around("@annotation(com.jinglin.annotation.RecordUserMessage)")
    public ResponseVO interceptorDo(ProceedingJoinPoint point) throws Throwable {
        ResponseVO responseVO = (ResponseVO) point.proceed();
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        RecordUserMessage annotation = method.getAnnotation(RecordUserMessage.class);
        if (annotation !=  null){
            /*
            * args是方法的实参  parameters是方法的形参。一一对应
            * */
            saveUserMessage(annotation,point.getArgs(),method.getParameters());
        }
        return responseVO;
    }


    private void saveUserMessage(RecordUserMessage annotation, Object[] args, Parameter[] parameters) {
        String videoId = null;
        Integer actionType = null;
        String  replyCommentId = null;
        VideoComment videoComment =   null;
        String content = null;
        MessageTypeEnum messageTypeEnum = null;
        for (int i = 0; i <parameters.length;i++){
            if (parameters[i].getName().equals("actionType")){
                actionType = (int) args[i];
            } else if (parameters[i].getName().equals("replyCommentId")){
                replyCommentId = (String) args[i];
            } else if (parameters[i].getName().equals("videoComment")){
                videoComment = (VideoComment) args[i];
                content = videoComment.getContent();
                videoId = videoComment.getVideoId();
            } else if (parameters[i].getName().equals("reason")){
                content = (String) args[i];
            }
        }
        // 默认的userAction都是like，所以我们需要在合理通过actionType参数来判断一下到底是视频like还是视频collect。
        if (UserActionTypeEnum.VIDEO_LIKE.getType().equals(actionType)){
            messageTypeEnum = MessageTypeEnum.LIKE;
        } else if (UserActionTypeEnum.VIDEO_COLLECT.getType().equals(actionType)){
            messageTypeEnum = MessageTypeEnum.COLLECTION;
        } else if (UserActionTypeEnum.VIDEO_COIN.getType().equals(actionType)){
            // 如果是投币，直接不记录消息。目前没有设置对应的业务
            return;
        } else {
            // 处理评论和系统通知
            messageTypeEnum = annotation.messageType();
        }
        TokenUserInfoDto tokenUserInfo = getTokenUserInfo();
        userMessageService.saveUserMessage(videoId,tokenUserInfo == null? null:tokenUserInfo.getUserId(),messageTypeEnum,content,replyCommentId);


    }


    private TokenUserInfoDto getTokenUserInfo(){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(Constants.TOKEN_WEB);
        return  (TokenUserInfoDto) redisComponent.getTokenInfo(token);
    }

}
